import socket
import sys
import threading

MSGLEN = 1024

class mysocket (threading.Thread):
	def __init__(self, sock=None):
		threading.Thread.__init__(self)
		if sock is None:
			try:
				self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			except socket.error:
				print ("socket error")
				sys.exit()
		else:
			self.sock = sock

	def run(self):
		self.run = True
		ping = ''
		while self.run:
			ping = self.myreceive()
			if ping.find('PING') == 0:
				ping.replace('PING', 'PONG')
				self.plainsend(ping)
				continue
			if ping.find('Global') == -1:
				msgOn2 = ping.split(':')
				if msgOn2[0] != '':
					print(ping)
					continue
				opAndTo12 = msgOn2[1].split(' ')
				if len(opAndTo12) != 4:
					print(ping)
					continue
				from01 = opAndTo12[0].split('!~')
				if len(from01) != 2:
					print(ping)
					continue
				if ping.find('PING') != -1:
					self.mysend('NOTICE '+from01[0]+' :'+msgOn2[2])
					continue
				print(from01[0]+' on '+opAndTo12[2]+':\n'+msgOn2[2])
			else:
				print(ping)
		print('Thread terminated')

	def connect(self, host, port):
		self.sock.connect((host, port))

	def mysend(self, msg):
		toSend = msg+'\r\n'
		sent = self.sock.sendall(toSend.encode('utf-8'))
		if sent == 0:
			raise RuntimeError('socket connection broken')
			
	def plainsend(self, msg):
		sent = self.sock.sendall(msg.encode('utf-8'))
		if sent == 0:
			raise RuntimeError('socket connection broken')

	def myreceive(self):
		try:
			result = self.sock.recv(MSGLEN).decode('utf-8')
		except socket.error:
			self.run = False
			result = 'connection closed'
		return result
		
	def test(self):
		msg = b''
		while True:
			chunk = self.sock.recv(1)
			msg += chunk
			if chunk == b'\n':
				break
		return msg
		
	def end(self):
		self.sock.close()
		

class operator:
	def __init__(self, server=None, nick=None):
		self.client = None
		self.actch = ''
		if nick is None:
			self.nick = None
		if server is None:
			self.server = None

	def start(self):
		self.client = mysocket()
		if self.server is None:
			self.server = input('please specify a server to connect:> ')
		if self.nick is None:
			self.nick = input('please enter your nick:> ')
		self.client.connect(self.server, 6667)
		self.initIrc()
		cin = ''
		self.client.start()
		while cin != '/quit':
			cin = input()
			if cin == '/quit':
				break
			elif cin.find('/set') == 0:
				self.actch = cin.split(' ')[1]
				print('active channel set to {}'.format(self.actch))
			elif cin.find('/msg') == 0:
				spl = cin.split(' ')
				cin = 'PRIVMSG '+spl[1]+' :'
				for i in range(2, len(spl)):
					cin += spl[i]+' '
				self.client.mysend(cin)
			elif cin.find('/plain') == 0:
				cin = cin.split('/plain')[1]
				self.client.mysend(cin)
			elif cin.find('/join') == 0:
				cin = cin.split('/join')[1]
				self.actch = cin
				self.client.mysend('JOIN '+cin)
			elif cin.find('/part') == 0:
				cin = cin.split('/part')[1]
				if self.actch == cin:
					self.actch = ''
				self.client.mysend('PART '+cin)
			elif self.actch != '':
				send = 'PRIVMSG '+self.actch+' :'+cin
				self.client.mysend(send)
			else:
				print('no channel is set or unknown cmd')
		self.client.mysend('QUIT :')
		self.client.run = False
		self.quitIrc()
                

	def initIrc(self):
		self.client.mysend('CAP LS')
		self.client.mysend('NICK {}'.format(self.nick))
		self.client.mysend('USER {} 0 * :...'.format(self.nick))
		ping = ''
		while ping.find('PING') == -1:
			ping = self.client.myreceive()
			print(ping)
		ping = ping.replace('PING', 'PONG')
		self.client.plainsend(ping)

	def quitIrc(self):
		self.client.mysend('QUIT :GOOD BYE')
		self.client.end()



op = operator()
op.start()
